﻿using System;
using System.Threading;
using GSE.Rpc;

namespace GSE
{
    class PushTask
    {
        protected EventPushReg eventPushReg;

        /// <summary>
        /// 下以帧的ID.
        /// </summary>
        protected int nextSeqId = 0;
        protected Mutex nextSeqIdResetLock;
        protected pushDataSender dataSender;
        protected string subName;
        protected byte seriesID;

        public PushTask(EventPushReg r, string subName, byte seriesID, pushDataSender dataSender)
        {
            this.eventPushReg = r;
            this.subName = subName;
            this.seriesID = seriesID;
            nextSeqIdResetLock = new Mutex();
            this.dataSender = dataSender;
        }
        protected ILogger logger
        {
            get { return Logger.Default; }
        }

        protected UInt16 GenSeqId()
        {
            var seq = Interlocked.Increment(ref nextSeqId);
            if (seq > 50000)
            {// 预留10000左右,避免溢出.
                nextSeqIdResetLock.WaitOne();
                if (nextSeqId > 5000)
                {
                    nextSeqId = 0;
                }// else 已经被其它线程重置过了.
                nextSeqIdResetLock.ReleaseMutex();
            }
            return (UInt16)(seq - 1);
        }

        public void Run(Object state)
        {
            var m = eventPushReg.Bump();
            if (m.Length < 1)
            {
                return;
            }
            var seqId = GenSeqId();
            var push = new Push(seriesID, seqId, m);
            try
            {
                dataSender(push.Encode());
                logger.Debug($"event pushed, name: {subName}, seriesID: {seriesID}, seqId: {seqId}");
            }
            catch (Exception ex)
            {
                logger.Warn($"failed to push event data: {ex.Message}");
            }
        }
    }
}
